package com.lxx.utils;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.Context;
import org.apache.catalina.Manager;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lxx.annotation.SystemPropertyName;
import com.lxx.dto.SystemInfo;
import com.lxx.utilsx.DateUtils;

public class SystemInfoUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(SystemInfoUtils.class);
	
	private static final long SECOND = 1000; // 单位,毫秒
	private static final long MINUTE = SECOND * 60;
	private static final long HOUR = MINUTE * 60;
	private static final long DAY = HOUR * 24;
	private static final long WEEK = DAY * 7;
	private static final long MONTH = DAY * 30;
	private static final long YEAR = DAY * 365;
	
	private static final int KB_BYTES = 1024;
	private static final int MB_BYTES = 1024 * KB_BYTES;
	private static final long GB_BYTES = 1024L * MB_BYTES;
	
	private enum TimeInterval{
		SECOND(SystemInfoUtils.SECOND, "秒"),
		MINUTE(SystemInfoUtils.MINUTE, "分"),
		HOUR(SystemInfoUtils.HOUR, "小时"),
		DAY(SystemInfoUtils.DAY, "天"),
		WEEK(SystemInfoUtils.WEEK, "周"),
		MONTH(SystemInfoUtils.MONTH, "月"),
		YEAR(SystemInfoUtils.YEAR, "年");
		
		private long interval;
		private String unit;
		private TimeInterval(long interval, String unit) {
			this.interval = interval;
			this.unit = unit;
		}
	}
	
	private static final TimeInterval[] ALL_TIME_INTERVALS = {TimeInterval.YEAR, TimeInterval.MONTH, TimeInterval.WEEK, TimeInterval.DAY, TimeInterval.HOUR, TimeInterval.MINUTE, TimeInterval.SECOND};
	
	

	public static final SystemInfo getSystemInfo() {
		SystemInfo systemInfo = new SystemInfo();
        
        try {
        	systemInfo.setServerTime(DateUtils.format(new Date()));
        	long curMills = System.currentTimeMillis();
        	systemInfo.setAlreadyRunTime(formatTimeInterval(curMills - Config.startRunTime));
        	
        	Runtime runtime = Runtime.getRuntime();
        	systemInfo.setCpuInfo(getCpuInfo());
        	systemInfo.setCpuNum(String.valueOf(runtime.availableProcessors()));
        	
        	systemInfo.setTotalMemory(String.format("%s MB", runtime.totalMemory() / MB_BYTES));
        	systemInfo.setFreeMemory(String.format("%s MB", runtime.freeMemory() / MB_BYTES));
        	systemInfo.setMaxMemory(String.format("%s MB", runtime.maxMemory() / MB_BYTES));
        	
        	MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
        	MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();
        	systemInfo.setUsedMemory(String.format("%s MB", memoryUsage.getUsed() / MB_BYTES));
        	
			Map<String,String> map = System.getenv();
			systemInfo.setServerUsername(map.get("USERNAME"));
			systemInfo.setDomain(map.get("USERDOMAIN"));
	        
	        
	        InetAddress addr = InetAddress.getLocalHost();   
            String ip=addr.getHostAddress().toString(); //获取本机ip  
            String hostName=addr.getHostName().toString(); //获取本机计算机名称  
            systemInfo.setServerIp(ip);
            systemInfo.setServerHost(hostName);
			
			InetAddress address = InetAddress.getLocalHost();  
			NetworkInterface ni = NetworkInterface.getByInetAddress(address);  
			byte[] mac = ni.getHardwareAddress();  
			String sMAC = "";  
			Formatter formatter = new Formatter();
			for (int i = 0; i < mac.length; i++) {  
			    sMAC = formatter.format(Locale.getDefault(), "%02X%s", mac[i],  
			            (i < mac.length - 1) ? "-" : "").toString();  
			}
			formatter.close();
			systemInfo.setMac(sMAC);
			
			Properties props=System.getProperties();  
			Class<SystemInfo> clazz = SystemInfo.class;
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				SystemPropertyName[] propertyNames = field.getDeclaredAnnotationsByType(SystemPropertyName.class);
				if (propertyNames.length > 0) {
					String value = props.getProperty(propertyNames[0].value());
					if (value != null) {
						field.setAccessible(true);
						field.set(systemInfo, value);
						field.setAccessible(false);
					}
				}
			}
			
			LOGGER.info("systemInfo: {}", systemInfo);
			
		} catch (Exception e) {
			LOGGER.error("", e);
		}   
        return systemInfo;
	}
	
	/**
	 * 将时间差转换成字符串显示,例如2h14min
	 * @param mills 毫秒数
	 * @return
	 */
	private static String formatTimeInterval(long mills) {
		StringBuffer sb = new StringBuffer();
		for (TimeInterval it : ALL_TIME_INTERVALS) {
			if (mills > it.interval) {
				sb.append(mills / it.interval).append(it.unit);
				mills = mills % it.interval;
			} else if (sb.length() > 0) {
				sb.append(mills).append(it.unit);
			}
		}
		return sb.toString();
	}
	
	private static final String getCpuInfo() {
		return CommandUtils.execWithRet("wmic cpu get name").get(1);
	}
	
	public static final int getSessionNum(HttpServletRequest request) {
		int activeSessions = 0;
		if (request instanceof RequestFacade) {
			try {
				Field requestField = request.getClass().getDeclaredField("request");
				requestField.setAccessible(true);
				Request req = (Request) requestField.get(request);
				Context context = req.getContext();
				Manager manager = context.getManager();
				activeSessions = manager.getActiveSessions();
			} catch (Exception e) {
				LOGGER.error("", e);
			}
		}
		return activeSessions;
	}

	public static void main(String[] args) {
//		getSystemInfo();
//		System.out.println(formatTimeInterval(1000 * 60 * 85+5));
		MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    	MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();
    	System.out.println(memoryUsage.getUsed());
	}
}
